#include "fileslist.hpp"

#include <dirent.h>
#include <cstdlib>
#include <sys/stat.h>
#include <stack>
#include <string>

using namespace std;

FilesList::FilesList(QString root,QDateTime minDate,QDateTime maxDate,qint64 minSize,qint64 maxSize,QMutex *mut_fl,QSemaphore *sem,QObject *parent):QList<QFileInfo *>(),QThread(parent),minDate(minDate),maxDate(maxDate),minSize(minSize),maxSize(maxSize),mut_fl(mut_fl),sem(sem){
	if(!root.endsWith('/'))
		root+='/';
	this->root=root;
	this->terminated=false;
}

FilesList::FilesList(const FilesList& fl):QList<QFileInfo *>(),QThread(fl.parent()){
}

FilesList::~FilesList(){
	for(FilesList::iterator it=this->begin();it!=this->end();it++){
		delete *it;
	}
}

void FilesList::run(){
	this->makeList();
}

void FilesList::stop(){
	this->terminated=true;
}

void FilesList::makeList(){
	for(FilesList::iterator it=this->begin();it!=this->end();it++){
		delete *it;
	}

	stack<string> stk;
	struct stat buf;
	const struct dirent *namelist=(struct dirent *)(malloc(sizeof(struct dirent)));
	DIR *ptr;
	
	stk.push(this->root.toStdString());
	while(!stk.empty() && !this->terminated){
		string dir=stk.top();
		stk.pop();
		ptr = opendir(dir.c_str());
		if ( ptr != NULL ){
			while((namelist = readdir(ptr))!=NULL && !this->terminated){
				string d_name=namelist->d_name;
				lstat( (dir+d_name).c_str(), &buf);
				if (S_ISDIR(buf.st_mode)){
					if(d_name!="." && d_name!=".."){
						stk.push(dir+d_name+"/");
					}
				}
				else{
					if (S_ISREG(buf.st_mode)){
						QFileInfo *pt;
						if (QFile::exists(QString((dir+d_name).c_str())))
							pt=new QFileInfo(QString((dir+d_name).c_str()));
						else
							if(QFile::exists(QString::fromUtf8((dir+d_name).c_str())))
								pt=new QFileInfo(QString::fromUtf8((dir+d_name).c_str()));
							else
								if(QFile::exists(QString::fromAscii((dir+d_name).c_str())))
									pt=new QFileInfo(QString::fromAscii((dir+d_name).c_str()));
								else
									if(QFile::exists(QString::fromLatin1((dir+d_name).c_str())))
										pt=new QFileInfo(QString::fromLatin1((dir+d_name).c_str()));
									else//colocar sinal aki para ser captado na interface
										continue;
						if(pt->suffix()!=""){
							if((pt->isHidden() && pt->suffix()==pt->completeSuffix())){
								delete pt;
							}
							else{
								bool todel=true;
								for(;;){
									if(this->minSize>=0)
										if(pt->size()<this->minSize)
											break;
									if(this->maxSize>0)
										if(pt->size()>this->maxSize)
											break;
									if(!this->maxDate.isNull())
										if(pt->lastModified()>this->maxDate)
											break;
									if(!this->minDate.isNull())
										if(pt->lastModified()<this->minDate)
											break;
									mut_fl->lock();
									this->push_back(pt);
									sem->release(1);
									mut_fl->unlock();
									todel=false;
									break;
								}
								if(todel){
									delete pt;
								}
							}
						}
						else
							delete pt;
					}
				}
			}
			closedir(ptr);
		}
	}
	if(namelist && !terminated)
		delete namelist;
}
